home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Forever 4
/
Atari Forever 4.zip
/
Atari Forever 4.iso
/
PD_THEMA
/
EDITOREN
/
7UP_PD
/
DRAGDROP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-14
|
13KB
|
563 lines
/*
* Drag & drop sample code.
* Copyright 1992 Atari Corporation
*
* global variables used:
* gl_apid: our AES application id
*
* BUGS/CAVEATS:
* This code is not re-entrant (it uses a static
* variable for the pipe name and for saving the
* SIGPIPE signal handler).
*
* While doing the drag and drop, the SIGPIPE
* signal (write on an empty pipe) is ignored
*/
#include <portab.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tos.h>
#include <aes.h>
#include "dragdrop.h"
#ifndef EACCDN
#define EACCDN -36
#endif
#ifndef SIGPIPE
#define SIGPIPE 13
#endif
#ifndef SIG_IGN
#define SIG_IGN 1L
#endif
#ifndef WF_OWNER
#define WF_OWNER 20
#endif
#ifndef FA_HIDDEN
#define FA_HIDDEN 0x2
#endif
extern int gl_apid;
static char pipename[] = "U:\\PIPE\\DRAGDROP.AA";
static long oldpipesig;
#ifdef DEBUGGING
#define debug_alert(x, y) form_alert(x, y)
#else
#define debug_alert(x, y)
#endif
/* Code for originator */
/*
* create a pipe for doing the drag & drop,
* and send an AES message to the receipient
* application telling it about the drag & drop
* operation.
*
* Input Parameters:
* apid: AES id of the window owner
* winid: target window (0 for background)
* msx, msy: mouse X and Y position
* (or -1, -1 if a fake drag & drop)
* kstate: shift key state at time of event
*
* Output Parameters:
* exts: A 32 byte buffer into which the
* receipient's 8 favorite
* extensions will be copied.
*
* Returns:
* A positive file descriptor (of the opened
* drag & drop pipe) on success.
* -1 if the receipient doesn't respond or
* returns DD_NAK
* -2 if appl_write fails
*/
/*
int
ddcreate(apid, winid, msx, msy, kstate, exts)
int apid, winid, msx, msy, kstate;
char exts[];
{
int fd, i;
int msg[8];
long fd_mask;
char c;
pipename[17] = pipename[18] = 'A';
fd = -1;
do {
pipename[18]++;
if (pipename[18] > 'Z') {
pipename[17]++;
if (pipename[17] > 'Z')
break;
}
/* FA_HIDDEN means "get EOF if nobody has pipe open for reading" */
fd = Fcreate(pipename, FA_HIDDEN);
} while (fd == EACCDN);
if (fd < 0) {
debug_alert(1, "[1][Fcreate error][OK]");
return fd;
}
/* construct and send the AES message */
msg[0] = AP_DRAGDROP;
msg[1] = gl_apid;
msg[2] = 0;
msg[3] = winid;
msg[4] = msx;
msg[5] = msy;
msg[6] = kstate;
msg[7] = (pipename[17] << 8) | pipename[18];
i = appl_write(apid, 16, msg);
if (i == 0) {
debug_alert(1, "[1][appl_write error][OK]");
Fclose(fd);
return -2;
}
/* now wait for a response */
fd_mask = 1L << fd;
i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
if (!i || !fd_mask) { /* timeout happened */
debug_alert(1, "[1][ddcreate: Fselect timeout][OK]");
abort_dd:
Fclose(fd);
return -1;
}
/* read the 1 byte response */
i = Fread(fd, 1L, &c);
if (i != 1 || c != DD_OK) {
if (i != 1)
debug_alert(1, "[1][ddcreate: read error][OK]");
else
debug_alert(1, "[1][ddcreate: DD_NAK][OK]");
goto abort_dd;
}
/* now read the "preferred extensions" */
i = Fread(fd, DD_EXTSIZE, exts);
if (i != DD_EXTSIZE) {
debug_alert(1, "[1][Error reading extensions][OK]");
goto abort_dd;
}
oldpipesig = Psignal(SIGPIPE, SIG_IGN);
return fd;
}
*/
/*
* see if the receipient is willing to accept a certain
* type of data (as indicated by "ext")
*
* Input parameters:
* fd file descriptor returned from ddcreate()
* ext pointer to the 4 byte file type
* name pointer to the name of the data
* size number of bytes of data that will be sent
*
* Output parameters: none
*
* Returns:
* DD_OK if the receiver will accept the data
* DD_EXT if the receiver doesn't like the data type
* DD_LEN if the receiver doesn't like the data size
* DD_NAK if the receiver aborts
*/
/*
int
ddstry(fd, ext, name, size)
int fd;
char *ext, *name;
long size;
{
Word hdrlen, i;
char c;
/* 4 bytes for extension, 4 bytes for size, 1 byte for
* trailing 0
*/
hdrlen = 9 + strlen(name);
i = Fwrite(fd, 2L, &hdrlen);
/* now send the header */
if (i != 2) return DD_NAK;
i = Fwrite(fd, 4L, ext);
i += Fwrite(fd, 4L, &size);
i += Fwrite(fd, (long)strlen(name)+1, name);
if (i != hdrlen) return DD_NAK;
/* wait for a reply */
i = Fread(fd, 1L, &c);
if (i != 1) return DD_NAK;
return c;
}
*/
/* Code for either receipient or originator */
/*
* close a drag & drop operation
*/
void
ddclose(fd)
int fd;
{
(void)Psignal(SIGPIPE, oldpipesig);
(void)Fclose(fd);
}
/* Code for receipient */
/*
* open a drag & drop pipe
*
* Input Parameters:
* ddnam: the pipe's name (from the last word of
* the AES message)
* preferext: a list of DD_NUMEXTS 4 byte extensions we understand
* these should be listed in order of preference
* if we like fewer than DD_NUMEXTS extensions, the
* list should be padded with 0s
*
* Output Parameters: none
*
* Returns:
* A (positive) file handle for the drag & drop pipe, on success
* -1 if the drag & drop is aborted
* A negative error number if an error occurs while opening the
* pipe.
*/
int
ddopen(ddnam,preferext)
int ddnam;
char *preferext;
{
int fd;
char outbuf[DD_EXTSIZE+1];
pipename[18] = ddnam & 0x00ff;
pipename[17] = (ddnam & 0xff00) >> 8;
fd = Fopen(pipename, 2);
if (fd < 0) return fd;
outbuf[0] = DD_OK;
strncpy(outbuf+1, preferext, DD_EXTSIZE);
oldpipesig = Psignal(SIGPIPE, SIG_IGN);
if (Fwrite(fd, (long)DD_EXTSIZE+1, outbuf) != DD_EXTSIZE+1) {
ddclose(fd);
return -1;
}
return fd;
}
/*
* ddrtry: get the next header from the drag & drop originator
*
* Input Parameters:
* fd: the pipe handle returned from ddopen()
*
* Output Parameters:
* name: a pointer to the name of the drag & drop item
* (note: this area must be at least DD_NAMEMAX bytes long)
* whichext: a pointer to the 4 byte extension
* size: a pointer to the size of the data
*
* Returns:
* 0 on success
* -1 if the originator aborts the transfer
*
* Note: it is the caller's responsibility to actually
* send the DD_OK byte to start the transfer, or to
* send a DD_NAK, DD_EXT, or DD_LEN reply with ddreply().
*/
int
ddrtry(fd, name, whichext, size)
int fd;
char *name;
long *size;
char *whichext;
{
Word hdrlen;
int i;
char buf[80];
i = Fread(fd, 2L, &hdrlen);
if (i != 2) {
return -1;
}
if (hdrlen < 9) { /* this should never happen */
return -1;
}
i = Fread(fd, 4L, whichext);
if (i != 4) {
return -1;
}
whichext[4] = 0;
i = Fread(fd, 4L, size);
if (i != 4) {
return -1;
}
hdrlen -= 8;
if (hdrlen > DD_NAMEMAX)
i = DD_NAMEMAX;
else
i = hdrlen;
if (Fread(fd, (long)i, name) != i) {
return -1;
}
hdrlen -= i;
/* skip any extra header */
while (hdrlen > 80) {
Fread(fd, 80L, buf);
hdrlen -= 80;
}
if (hdrlen > 0)
Fread(fd, (long)hdrlen, buf);
return 0;
}
/*
* send a 1 byte reply to the drag & drop originator
*
* Input Parameters:
* fd: file handle returned from ddopen()
* ack: byte to send (e.g. DD_OK)
*
* Output Parameters:
* none
*
* Returns: 0 on success, -1 on failure
* in the latter case the file descriptor is closed
*/
int
ddreply(fd, ack)
int fd, ack;
{
char c = ack;
if (Fwrite(fd, 1L, &c) != 1L) {
Fclose(fd);
}
return 0;
}
#if 1
/******************************************************************
* Here are some sample functions that use the *
* drag & drop functions above to implement the protocol. *
* These are not complete, working functions yet, but are *
* intended to serve as a "skeleton" for the actual *
* functions that would appear in a drag & drop application. *
* *
* The following global variables are defined: *
* gl_ourexts: the drag & drop data types we understand *
******************************************************************/
/* modify this as necessary */
char gl_ourexts[DD_EXTSIZE] = "ARGS.RTF.TXT";
/*
* rec_ddmsg: given a drag & drop message, act as
* a receipient and get the data
*
* Input Parameters:
* msg: Pointer to the 16 byte AES message
* returned by evnt_multi or evnt_mesag
*
* calls the following functions to actually perform the paste
* operation:
*
* parseargs(char cmdlin[]):
* Given a null terminated string of arguments, separated
* by spaces, parse it and perform whatever actions are
* appropriate on the arguments (usually file and folder
* names)
*
* paste_rtf(int win, int fd, long size):
* Read "size" bytes from the open file descriptor "fd",
* and paste it into the window whose handle is "win".
* The data is assumed to be in RTF format.
*
* paste_txt(int win, int fd, long size):
* Read "size" bytes from the open file descriptor "fd",
* and paste it into the window whose handle is "win".
* The data is assumed to be ASCII text.
*/
void rec_ddmsg(int msg[], char *pathname)
{
int winid;
int msx, msy, kstate;
int fd, pnam;
int i;
char txtname[DD_NAMEMAX], ext[5];
char *cmdline;
long size;
winid = msg[3];
msx = msg[4];
msy = msg[5];
kstate = msg[6];
pnam = msg[7];
/*********************************************/
/*
if(getenv("UNIXMODE")!=NULL)
pipename[2]=pipename[7]='/';
else
*/
pipename[2]=pipename[7]='\\';
/*********************************************/
fd = ddopen(pnam, gl_ourexts);
if (fd < 0) return;
for(;;) {
i = ddrtry(fd, txtname, ext, &size);
if (i < 0) {
ddclose(fd);
return;
}
if (!strncmp(ext, "ARGS", 4)) {
cmdline = malloc((size_t)size+1);
if (!cmdline) {
ddreply(fd, DD_LEN);
continue;
}
ddreply(fd, DD_OK);
Fread(fd, size, cmdline);
ddclose(fd);
cmdline[size] = 0;
strcpy(pathname,cmdline);
free(cmdline);
return;
}
else if (!strncmp(ext, ".RTF", 4)) {
ddreply(fd, DD_OK);
/*
paste_rtf(winid, fd, size);
*/
ddclose(fd);
return;
}
else if (!strncmp(ext, ".TXT", 4)) {
ddreply(fd, DD_OK);
/*
paste_txt(winid, fd, size);
*/
ddclose(fd);
return;
}
ddreply(fd, DD_EXT);
#ifdef DEBUGGING
{ char foo[40];
strcpy(foo, "[1][rec_ddmsg: unknown extension: |");
strcat(foo, ext);
strcat(foo, "][OK]");
debug_alert(1, foo);
}
#endif /* DEBUGGING */
}
}
/*
* send_ddmsg: construct and send a drag & drop message;
* we only can send the 1 type of data (specified
* by ext)
*
* Input Parameters:
* msx, msy: coordinates where data was dropped
* kstate: keyboard state at time of drop
* name: name of the data
* ext: data type (4 byte extension)
* size: size of data
* data: pointer to data
*
* Output Parameters: none
*
* Returns:
* 0 on success
* 1 if no window was found
* 2 if the window belongs to us
* 3 if the receipient didn't accept the data
* or a negative error code from the functions
* above
*/
/*
int
send_ddmsg(msx, msy, kstate, name, ext, size, data)
int msx, msy, kstate;
char *name, *ext;
long size;
char *data;
{
int fd;
int apid, winid;
int dummy, i;
char recexts[DD_EXTSIZE];
extern int gl_apid;
winid = wind_find(msx, msy);
if (!winid) {
debug_alert(1, "[1][Window not found][OK]");
return 1;
}
if (!_wind_get(winid, WF_OWNER, &apid, &dummy, &dummy, &dummy)) {
debug_alert(1, "[1][Owner not found][OK]");
return 2;
}
if (apid == gl_apid) {
debug_alert(1, "[1][Same owner][OK]");
return 1; /* huh? that shouldn't happen */
}
fd = ddcreate(apid, winid, msx, msy, kstate, recexts);
if (fd < 0) {
debug_alert(1, "[1][Couldn't open pipe][OK]");
return fd;
}
if ((i = ddstry(fd, ext, name, size)) != DD_OK) {
if (i == DD_EXT) {
debug_alert(1, "[1][Bad extension][OK]");
} else {
debug_alert(1, "[1][Receiver canceled][OK]");
}
ddclose(fd);
return 3;
}
Fwrite(fd, size, data);
ddclose(fd);
return 0;
}
*/
#endif /* 0 */